<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // var timer1 = null;
      // var timer2 = null;
      // var timer3 = null;
      // var timer4 = null;
      // var timer5 = null;
      //闭包的特性

      //是一个闭包
      //闭包:一个函数 可以访问到外部的变量 那么 外部上下文环境对这个函数形成了包围,这个环境在内存里不会被销毁
      //闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment  词法环境)的引用的组合  换而言之 闭包让开发者可以从内部函数访问外部函数的作用域  在JavaScript中 闭包会随着函数的创建而被同时创建

      //全局变量不会被销毁
      // var a = 10;
      // function fn() {
      //   console.log(a);
      // }
      // fn();

      //1.创建函数 2.调用函数 3.销毁函数内的一些变量
      // function fn() {
      //   var a = 10;
      //   console.log(a);
      // }
      // fn(); //函数被调用后 函数内容会被销毁 a也就不存在 is not defined
      // console.log(a);

      //常用闭包一
      //占用内存
      /*  function fn() {
        var a = 10;
        function fn2() {
          console.log(a);
        }
        return fn2;
      }
      var myfn = fn();
      myfn(); */

      //闭包的缓存特性
      //让下面的fn函数只执行一次
      function fn() {
        console.log("需要执行的函数");
      }
      //高阶函数 有函数作为输入或者是输出的函数被称为高阶函数
      function execFn(fn) {
        var flag = false; //代表fn是否执行了  false是fn没有执行
        return function () {
          if (!flag) {
            //flag默认false  取反为true  当没有调用的时候调用fn(),弹出需要执行的函数,然后取反,flag为true
            //再次调用的时候,if判断走的是下面的else  弹出这个函数已经被执行过了
            fn();
            flag = !flag;
          } else {
            console.log("这个函数已经被执行过了");
          }
        };
      }
      var mufn = execFn(fn);
      mufn();
      mufn();

      // 小练习 ： 把三元参数传成一元参数 （柯里化curry）
      function add(x, y, z) {
        //三元函数,几元就是几个参数
        return x + y + z;
      }

      function curryFn(add) {
        return function (x) {
          return function (y) {
            return function (z) {
              return add(x, y, z);
            };
          };
        };
      }
      var myadd = curryFn(add);
      var res = myadd(1)(2)(3); //一元函数
      console.log(res);
    </script>
  </body>
</html>
